import express from 'express';
import {client, signJWT} from './scheme.js';
import type {jwtPayload} from './scheme.js';
import bcrypt from 'bcryptjs';
import JWT from 'jsonwebtoken';

const routeUser = express.Router();

routeUser.post('/register', async (req, res) => {
  try {
    const {userParam} = req.body;
    const {email, password, name} = userParam;
    const operationResult = await client.user.create({
      data: {
        email: email,
        password: await bcrypt.hash(password, await bcrypt.genSalt()),
        userName: (name === undefined) ? email : name
      }
    });
    if(!operationResult) {
      res.status(507).json({
        timestamp: new Date().getTime(),
        api: { version: 'v1.0', status: 507 },
        result: {description: '注册失败'}
      });
    }
    const payload: jwtPayload = { aud: email };
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 200 },
      result: {
        description: '用户创建成功',
        userConfig: { 
          email: operationResult.email,
          name: operationResult.userName,
          userID: operationResult.userID
        },
        token: signJWT(payload)
      }
    });
  } catch (e) {
    return res.json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 403},
      result: {
        description: '注册失败，邮箱可能已使用',
      }
    });
  }
});

routeUser.post('/login', async (req, res) => {
  try {
    const {userParam} = req.body;
    const {email, password} = userParam;
    const userInfo = await client.user.findFirstOrThrow({
      where: { email: email }
    });
    const loginSucceed = bcrypt.compareSync(password, userInfo.password);
    if(!loginSucceed) {
      return res.status(200).json({
        timestamp: new Date().getTime(),
        api: { version: 'v1.0', status: 401 },
        result: {description: '身份核验失败'}
      });
    }
    const payload: jwtPayload = { aud: email };
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 200 },
      result: {
        description: '登陆成功',
        userConfig: { 
          email: userInfo.email,
          name: userInfo.userName,
          userID: userInfo.userID
        },
        token: signJWT(payload)
      }
    });
  } catch (NotFoudError) {
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 401 },
      result: {description: '用户不存在'}
    });
  }
});

routeUser.post('/changeName', async (req, res) => {
  const {param} = req.body;
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const {user: {email}, newConfig: {newName}} = param;
  const operationResult = await client.user.update({
    where: {email: email},
    data: {userName: newName}
  });
  if(!operationResult){
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 204 },
      result: {description: '用户名更新异常'}
    });
  }
  return res.status(200).json({
    timestamp: new Date().getTime(),
    api: { version: 'v1.0', status: 200 },
    result: {
      description: '用户名更新成功',
      newConfig: { newName: newName }
    }
  });
});

routeUser.post('/changePassword', async (req, res) => {
  const {param} = req.body;
  const {user: {email, oldPassword}, newConfig: {newPassword}} = param;
  const userConfig = await client.user.findFirstOrThrow({
    where: {email: email}
  });
  const authrFlag = bcrypt.compareSync(oldPassword, userConfig.password);
  if(!authrFlag) {
    return res.status(507).json({
      timestamp: new Date().getTime(),
      api: {
        version: 'v1.0',
        status: 401
      },
      result: {
        description: '密码错误'
      }
    });
  }
  const operationResult = await client.user.update({
    where: {email: email},
    data: {
      password: await bcrypt.hash(newPassword, await bcrypt.genSalt())
    }
  });
  if(operationResult) {
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 200 },
      result: {
        description: '密码修改成功',
        user: {
          email: userConfig.email,
          userID: userConfig.userID,
          userName: userConfig.userName
        }
      }
    });
  }
});

routeUser.post('/getUserProfile', async (req, res) => {
  const author = req.headers.authorization;
  if(author === undefined){
    return res.status(507).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 401 },
      result: { description: '鉴权失败' }
    });
  }
  try {
    const token = JWT.decode(author, {json: true});
    if(token === null){
      return res.status(507).json({
        timestamp: new Date().getTime(),
        api: { version: 'v1.0', status: 401 },
        result: { description: '鉴权失败' }
      });
    }
    if(token.aud === undefined) {
      return res.status(507).json({
        timestamp: new Date().getTime(),
        api: { version: 'v1.0', status: 401 },
        result: { description: 'token没有有效用户' }
      });
    }
    const userProfile = await client.user.findFirstOrThrow({
      where: {email: token.aud as string}
    });
    return res.status(200).json({
      timestamp: new Date().getTime(),
      api: {version: 'v1.0', status: 200},
      result: {
        description: '查询成功',
        user: {
          email: userProfile.email,
          userID: userProfile.userID,
          name: userProfile.userName
        }
      }
    });
  } catch (userNotFount) {
    return res.status(507).json({
      timestamp: new Date().getTime(),
      api: { version: 'v1.0', status: 401 },
      result: { description: '没有该用户' }
    });
  }
});

routeUser.post('/updateJWT', async (req, res) => {
  const author = req.headers.authorization;
  const token = JWT.decode(author as string, {json: true});
  const userEmail = token?.aud;
  return res.status(200).json({
    timestamp: new Date().getTime(),
    api: { version: 'v1.0', status: 200 },
    result: {
      description: '分发成功',
      newToken: signJWT({aud: userEmail as string})
    }
  });
});

export default routeUser;